<?php
/**
 * +------------------------------
 * Created by PhpStorm.
 * +------------------------------
 * User: xxx
 * +------------------------------
 * DateTime: 2019/12/4 20:23
 * +------------------------------
 */

namespace Core;


use Core\annotations\Bean;
use Doctrine\Common\Annotations\AnnotationReader;

class ClassFactory
{
    public static $beans = [];

    /**
     * 扫描所有实例上的注解，同时处理类注解，并实例化到 bean静态数组
     * @param string $path
     * @param string $namespace
     * @throws \Doctrine\Common\Annotations\AnnotationException
     * @throws \ReflectionException
     */
    public static function scanBeans(string $path, string $namespace)
    {

        //加载此；路径下所有php文件
        $phpfiles = glob($path . '/*.php');
        foreach ($phpfiles as $phpfile) {
            require($phpfile);
        }

        //取得所有定义的类 并过滤, 使用反射实例化
        $classes = get_declared_classes();
        $reader = new AnnotationReader();
        foreach ($classes as $class) {

            if (strstr($class, $namespace)) {
                $ref_class = new \ReflectionClass($class);
                $annos = $reader->getClassAnnotations($ref_class);

                foreach ($annos as $anno) {

                    //判断当前 anno对象是否为 Bean实例
                    if ($anno instanceof Bean) {
                        //写入静态数组
                        //self::$beans[$ref_class->getName()] = $ref_class->newInstance();
                        //同时完成属性注解 处理
                        self::$beans[$ref_class->getName()] = self::loadClass($ref_class->getName(), $ref_class->newInstance());
                    }
                }

            }

        }
        return;
    }

    /**
     * 获取bean实例
     * @param string $beanName
     * @return mixed|null
     */
    public static function getBean(string $beanName)
    {
        return isset(self::$beans[$beanName]) ? self::$beans[$beanName] : null;
    }

    /**
     * 载入类 并处理属性注解
     * @param string $clazz
     * @param bool $object
     * @return bool|object
     * @throws \Doctrine\Common\Annotations\AnnotationException
     * @throws \ReflectionException
     */
    public static function loadClass(string $clazz, $object = false)
    {

        $ref_class = new \ReflectionClass($clazz);
        $props = $ref_class->getProperties();
        //var_dump($props);

        $reader = new AnnotationReader();
        foreach ($props as $prop) {
            $annos = $reader->getPropertyAnnotations($prop);
            //var_dump($annos);

            foreach ($annos as $anno) {
                $getValue = $anno->do();
                $ref_obj = $object ? $object : $ref_class->newInstance();
                $prop->setValue($ref_obj, $getValue);
                return $ref_obj;
            }
        }

        return isset($object) ? $object : $ref_class->newInstance();

    }

}